/* Rafael Setra
 * Pd.8 Software Design
 * This program is a subclass of Game and is used to play the dragging game.
 */

import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

import javax.swing.JApplet;
import javax.swing.event.MouseInputListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;

       
public class DraggingGame extends Game implements MouseInputListener
{
	Image picture;
	Image offscreenImage;		
	Graphics offscreenGraphics;	
	MediaTracker tracker;
	Image[][] picPieces;
	Area[][] picAreas;
	Area[][] locationAreas;
	int idragged,jdragged,xClick,yClick,initX,initY,rows,columns;
	boolean start = true;
	boolean win = false;
	
	//constructor for the dragging game
	public DraggingGame(Image pic,int  r, int c)
	{
		rows = r;
		columns = c;
		picPieces = new Image[rows][columns];
		picAreas = new Area[rows][columns];
		locationAreas = new Area[rows][columns];
		addMouseMotionListener(this);
		addMouseListener(this);
		idragged=-1;jdragged=-1;xClick=-1;yClick=-1;
		tracker = new MediaTracker(this);
		picture = pic ;
		tracker.addImage(picture,1);   // add to media tracker
		initX=-1;initY=-1;
		try 
		{
			tracker.waitForAll();  // wait for images to fully load
		}//end try
		catch(InterruptedException e)
		{
		}//end catch
		int width = picture.getWidth(this)/columns;
		int height = picture.getHeight(this)/rows;
		
	    for(int i=0; i <rows; i++) 
	    	for(int j = 0; j < columns; j++) 
	    	{  
	    		picPieces[i][j] = new BufferedImage(width,height,BufferedImage.TYPE_3BYTE_BGR ); 
	    		Graphics2D g2 = (Graphics2D) picPieces[i][j].getGraphics();  
	          	g2.drawImage(picture, 0, 0, width, height, width*j, height*i, width*(j+1), height*(i+1), null);  
	         	g2.dispose(); 
	        }  //end for
	    int width2=picPieces[0][0].getWidth(this);
		int height2=picPieces[0][0].getHeight(this);
	    for(int i=0; i < rows; i++) 
	    	for(int j = 0; j < columns; j++) 
	    	{  
			    Rectangle2D.Double rect = new Rectangle2D.Double(getWidth()/20+width2*j,getHeight()/20+height2*i,width2,height2);
		     	locationAreas[i][j] = new Area(rect);
	    	}//end for
     	
	}//end DraggingGame

	//paints the class
	public void paintComponent(Graphics g)
	{
		offscreenImage = createImage(getWidth(),getHeight());
		offscreenGraphics = offscreenImage.getGraphics();	
		Graphics2D g2 = (Graphics2D)offscreenGraphics; ;
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		
		//draw this better with areas later
		
		int width=picPieces[0][0].getWidth(this);
		int height=picPieces[0][0].getHeight(this);
		
		  for(int i=0; i < rows; i++) 
		    	for(int j = 0; j < columns; j++) 
		    		offscreenGraphics.drawRect((int)(locationAreas[i][j].getBounds2D().getX()),(int)(locationAreas[i][j].getBounds2D().getY()),width,height);
//		  offscreenGraphics.drawImage(picture,(int)locationAreas[0][0].getBounds2D().getX(),(int)locationAreas[rows-1][0].getBounds2D().getMaxY()+20,this );
		  //draws full image onto the screen  
		  
		  
		if(start)
			for(int i=0;i<rows;i++)
				for(int j=0;j<columns;j++)
				{
					int xCor = (int)(getWidth()/2 + (getWidth()/2-picPieces[i][j].getWidth(this))*Math.random());
					int yCor = (int)((getHeight()-picPieces[i][j].getHeight(this))*Math.random());
					offscreenGraphics.drawImage(picPieces[i][j],xCor,yCor,this);
					picAreas[i][j]= new Area(new Rectangle2D.Double(xCor,yCor,width,height));
				}//end for
		else
		{
			for(int i=0;i<rows;i++)
				for(int j=0;j<columns;j++)
				{
					int xCor = (int)(picAreas[i][j].getBounds2D().getX());
					int yCor = (int)(picAreas[i][j].getBounds2D().getY());
					offscreenGraphics.drawImage(picPieces[i][j],xCor,yCor,this);
				}//end for
			if(idragged!=-1)
				offscreenGraphics.drawImage(picPieces[idragged][jdragged],(int)(picAreas[idragged][jdragged].getBounds2D().getX()),(int)(picAreas[idragged][jdragged].getBounds2D().getY()),this);
		}//end else
		start=false;
		g.drawImage(offscreenImage,0,0,this);
		
		
		if(win)
		{
			Font myFont = new Font("Serif", Font.BOLD, 36);
			g.setFont(myFont);
			g.drawString("Congratulations", getWidth()*1/4, getHeight()*4/5);
		}//end if
		
	}//end paintComponent
	
	
	public void mouseClicked(MouseEvent e) 
	{
	
	}

	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	
	//actions if the mouse is pressed
	public void mousePressed(MouseEvent e) 
	{
		for(int i=0;i<rows;i++)
			for(int j=0;j<columns;j++)
				if(picAreas[i][j].contains(e.getX(),e.getY()))
				{
					idragged=i;
					jdragged=j;
					xClick=e.getX();
					yClick=e.getY();
					initX=(int)(picAreas[i][j].getBounds2D().getX());
					initY=(int)(picAreas[i][j].getBounds2D().getY());
					break;
				}//end if
	}//end mousePressed

	//actions if the mouse is released
	public void mouseReleased(MouseEvent e) 
	{
		boolean change = true;
		
		if(idragged!=-1)
		{
			int xCor = (int)(picAreas[idragged][jdragged].getBounds2D().getX());
			int yCor = (int)(picAreas[idragged][jdragged].getBounds2D().getY());
			int width=picPieces[0][0].getWidth(this);
			int height=picPieces[0][0].getHeight(this);
			// fix overlapping pictures
			for(int i=0;i<rows;i++)
				for(int j=0;j<columns;j++)
				{	
					if(locationAreas[i][j].contains(xCor+width/2,yCor+height/2))
					{
						for(int k=0;k<rows;k++)
							for(int l=0;l<columns;l++)
								if(picAreas[k][l].equals(locationAreas[i][j]) && !(k==idragged && l==jdragged))
									change = false;
					
						if(change)
						{
							Rectangle2D.Double rect = new Rectangle2D.Double(locationAreas[i][j].getBounds2D().getX(),locationAreas[i][j].getBounds2D().getY(),width,height);
							picAreas[idragged][jdragged]= new Area(rect);
						}//end if
						else
						{
							Rectangle2D.Double rect = new Rectangle2D.Double(initX,initY,width,height);
							picAreas[idragged][jdragged]= new Area(rect);
						}//end else
						
					}//end if
				}//end for
		}//end if
		idragged=-1;
		jdragged=-1;
		initX=-1;
		initY=-1;
		xClick=-1;
		yClick=-1;
		
		win = true;
		for(int i=0;i<rows;i++)
			for(int j=0;j<columns;j++)
				if(!picAreas[i][j].equals(locationAreas[i][j]))
					win=false;
			
		
		repaint();
	}//end mouseReleased

	public void mouseDragged(MouseEvent e) 
	{
		if(idragged!=-1)
		{
			int xCor = (int)(picAreas[idragged][jdragged].getBounds2D().getX())+(e.getX()-xClick);
			int yCor = (int)(picAreas[idragged][jdragged].getBounds2D().getY())+(e.getY()-yClick);
			if(xCor>getWidth()-picPieces[0][0].getWidth(this))
				xCor=getWidth()-picPieces[0][0].getWidth(this);
			if(yCor>getHeight()-picPieces[0][0].getHeight(this))
				yCor=getHeight()-picPieces[0][0].getHeight(this);
			if(xCor<0)
				xCor=0;
			if(yCor<0)
				yCor=0;
			xClick=e.getX();
			yClick=e.getY();
			Rectangle2D.Double rect = new Rectangle2D.Double(xCor,yCor,picPieces[0][0].getWidth(this),picPieces[0][0].getHeight(this));
			picAreas[idragged][jdragged]= new Area(rect);
			repaint();
		}//end if
	}//end mouseDragged

	public void mouseMoved(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}
}//end draggingGame class